package main

import (
	"context"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"syscall"
	"unsafe"
)

// App struct
type App struct {
	ctx context.Context
}

// NewApp creates a new App application struct
func NewApp() *App {
	return &App{}
}

// startup is called when the app starts. The context is saved
// so we can call the runtime methods
func (a *App) startup(ctx context.Context) {
	a.ctx = ctx
}

// Greet returns a greeting for the given name
func (a *App) Greet(name string) string {
	return fmt.Sprintf("Hello %s, It's show time!", name)
}

// VideoProcessRequest 视频处理请求结构
type VideoProcessRequest struct {
	InputFile     string `json:"inputFile"`
	OutputFile    string `json:"outputFile"`
	Operation     string `json:"operation"`
	StartTime     string `json:"startTime"`
	Duration      string `json:"duration"`
	Format        string `json:"format"`
	Quality       string `json:"quality"`
	AudioFormat   string `json:"audioFormat"`
	AudioBitrate  string `json:"audioBitrate"`
}

// VideoProcessResponse 视频处理响应结构
type VideoProcessResponse struct {
	Success bool   `json:"success"`
	Message string `json:"message"`
	Output  string `json:"output"`
}

// ProcessVideo 处理视频文件
func (a *App) ProcessVideo(req VideoProcessRequest) VideoProcessResponse {
	// 获取FFmpeg可执行文件路径
	ffmpegPath := a.getFFmpegPath()
	if ffmpegPath == "" {
		return VideoProcessResponse{
			Success: false,
			Message: "FFmpeg not found",
		}
	}

	// 构建FFmpeg命令
	args := []string{"-i", req.InputFile}

	switch req.Operation {
	case "cut":
		if req.StartTime != "" {
			args = append(args, "-ss", req.StartTime)
		}
		if req.Duration != "" {
			args = append(args, "-t", req.Duration)
		}
	case "audio_cut":
		// 音频剪切：提取音频并剪切
		args = append(args, "-vn") // 不包含视频
		if req.StartTime != "" {
			args = append(args, "-ss", req.StartTime)
		}
		if req.Duration != "" {
			args = append(args, "-t", req.Duration)
		}
		// 设置音频编码器和比特率
		if req.AudioFormat != "" {
			switch req.AudioFormat {
			case "mp3":
				args = append(args, "-acodec", "libmp3lame")
			case "aac":
				args = append(args, "-acodec", "aac")
			case "wav":
				args = append(args, "-acodec", "pcm_s16le")
			case "flac":
				args = append(args, "-acodec", "flac")
			case "ogg":
				args = append(args, "-acodec", "libvorbis")
			}
		}
		if req.AudioBitrate != "" {
			args = append(args, "-ab", req.AudioBitrate)
		}
	case "convert":
		if req.Format != "" {
			args = append(args, "-f", req.Format)
		}
	case "extract_audio":
		args = append(args, "-vn", "-acodec", "copy")
	case "compress":
		if req.Quality != "" {
			args = append(args, "-crf", req.Quality)
		}
	}

	args = append(args, "-y", req.OutputFile)

	// 执行FFmpeg命令
	cmd := exec.Command(ffmpegPath, args...)
	output, err := cmd.CombinedOutput()

	if err != nil {
		return VideoProcessResponse{
			Success: false,
			Message: fmt.Sprintf("FFmpeg error: %v\nOutput: %s", err, string(output)),
		}
	}

	return VideoProcessResponse{
		Success: true,
		Message: "Video processed successfully",
		Output:  string(output),
	}
}

// getFFmpegPath 获取FFmpeg可执行文件路径
func (a *App) getFFmpegPath() string {
	// 首先尝试从应用程序目录查找
	exePath, err := os.Executable()
	if err == nil {
		exeDir := filepath.Dir(exePath)
		ffmpegPath := filepath.Join(exeDir, "ffmpeg", "ffmpeg.exe")
		if _, err := os.Stat(ffmpegPath); err == nil {
			return ffmpegPath
		}
	}

	// 尝试从系统PATH查找
	if path, err := exec.LookPath("ffmpeg"); err == nil {
		return path
	}

	return ""
}

// GetFFmpegInfo 获取FFmpeg信息
func (a *App) GetFFmpegInfo() map[string]interface{} {
	ffmpegPath := a.getFFmpegPath()
	if ffmpegPath == "" {
		return map[string]interface{}{
			"available": false,
			"message":   "FFmpeg not found",
		}
	}

	cmd := exec.Command(ffmpegPath, "-version")
	output, err := cmd.Output()
	if err != nil {
		return map[string]interface{}{
			"available": false,
			"message":   "Failed to get FFmpeg version",
		}
	}

	versionInfo := string(output)
	lines := strings.Split(versionInfo, "\n")
	version := "Unknown"
	if len(lines) > 0 {
		version = lines[0]
	}

	return map[string]interface{}{
		"available": true,
		"version":   version,
		"path":      ffmpegPath,
	}
}

// ScreenInfo 屏幕信息结构
type ScreenInfo struct {
	Width  int `json:"width"`
	Height int `json:"height"`
	Name   string `json:"name"`
}

// RecordRegion 录制区域结构
type RecordRegion struct {
	X      int `json:"x"`
	Y      int `json:"y"`
	Width  int `json:"width"`
	Height int `json:"height"`
}

// GetScreenInfo 获取屏幕信息
func (a *App) GetScreenInfo() []ScreenInfo {
	// Windows API调用获取屏幕信息
	user32 := syscall.NewLazyDLL("user32.dll")
	getSystemMetrics := user32.NewProc("GetSystemMetrics")
	
	width, _, _ := getSystemMetrics.Call(0)  // SM_CXSCREEN
	height, _, _ := getSystemMetrics.Call(1) // SM_CYSCREEN
	
	return []ScreenInfo{
		{
			Width:  int(width),
			Height: int(height),
			Name:   "主显示器",
		},
	}
}

// SelectDirectory 选择目录
func (a *App) SelectDirectory() string {
	// 使用Windows文件夹选择对话框
	shell32 := syscall.NewLazyDLL("shell32.dll")
	shBrowseForFolder := shell32.NewProc("SHBrowseForFolderW")
	shGetPathFromIDList := shell32.NewProc("SHGetPathFromIDListW")
	
	// 创建BROWSEINFO结构
	type BROWSEINFO struct {
		hwndOwner      uintptr
		pidlRoot       uintptr
		pszDisplayName uintptr
		lpszTitle      uintptr
		ulFlags        uint32
		lpfn           uintptr
		lParam         uintptr
		iImage         int32
	}
	
	title := syscall.StringToUTF16Ptr("选择输出目录")
	displayName := make([]uint16, 260)
	
	bi := BROWSEINFO{
		hwndOwner:      0,
		pidlRoot:       0,
		pszDisplayName: uintptr(unsafe.Pointer(&displayName[0])),
		lpszTitle:      uintptr(unsafe.Pointer(title)),
		ulFlags:        0x00000001, // BIF_RETURNONLYFSDIRS
		lpfn:           0,
		lParam:         0,
		iImage:         0,
	}
	
	pidl, _, _ := shBrowseForFolder.Call(uintptr(unsafe.Pointer(&bi)))
	if pidl == 0 {
		return "" // 用户取消选择
	}
	
	path := make([]uint16, 260)
	ret, _, _ := shGetPathFromIDList.Call(pidl, uintptr(unsafe.Pointer(&path[0])))
	if ret == 0 {
		return ""
	}
	
	return syscall.UTF16ToString(path)
}

// OpenDirectory 打开目录
func (a *App) OpenDirectory(path string) error {
	cmd := exec.Command("explorer", path)
	return cmd.Start()
}

// OpenFile 使用系统默认程序打开文件
func (a *App) OpenFile(filePath string) error {
	cmd := exec.Command("cmd", "/c", "start", "", filePath)
	return cmd.Start()
}

// GetDefaultRecordingPath 获取默认录制路径
func (a *App) GetDefaultRecordingPath() string {
	// 获取用户的视频文件夹
	homeDir, err := os.UserHomeDir()
	if err != nil {
		return "C:\\Users\\Public\\Videos"
	}
	
	videoDir := filepath.Join(homeDir, "Videos", "ScreenRecordings")
	
	// 确保目录存在
	os.MkdirAll(videoDir, 0755)
	
	return videoDir
}

// SaveRecordingFile 保存录制文件到指定目录
func (a *App) SaveRecordingFile(fileData []byte, fileName string, outputDir string) map[string]interface{} {
	// 确保输出目录存在
	err := os.MkdirAll(outputDir, 0755)
	if err != nil {
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("创建目录失败: %v", err),
		}
	}
	
	// 构建完整文件路径
	filePath := filepath.Join(outputDir, fileName)
	
	// 写入文件
	err = os.WriteFile(filePath, fileData, 0644)
	if err != nil {
		return map[string]interface{}{
			"success": false,
			"message": fmt.Sprintf("保存文件失败: %v", err),
		}
	}
	
	return map[string]interface{}{
		"success":  true,
		"message":  "文件保存成功",
		"filePath": filePath,
		"fileSize": len(fileData),
	}
}
